﻿// 中国象棋1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
//定义棋盘长宽的宏
#ifdef WIDTH
#undef WIDTH
#endif
#define WIDTH 800

#ifdef HEIGHT
#undef HEIGHT 
#endif
#define HEIGHT 800

//定义棋子图片长宽
#define PIECE_WIDTH 76
#define PIECE_HEIGHT 76

#include <iostream>
#include <graphics.h>
#include "Chess.h"
using namespace std;

//加载棋盘图片
IMAGE* playImg = new IMAGE();
IMAGE* boardImg = new IMAGE();

//棋子图片
IMAGE* rSoldierImg = new IMAGE();
IMAGE* rCarImg = new IMAGE();
IMAGE* rHorseImg = new IMAGE();
IMAGE* rCannonImg = new IMAGE();
IMAGE* rGuardImg = new IMAGE();
IMAGE* rKingImg = new IMAGE();
IMAGE* rElephant = new IMAGE();

IMAGE* bSoldierImg = new IMAGE();
IMAGE* bCarImg = new IMAGE();
IMAGE* bHorseImg = new IMAGE();
IMAGE* bCannonImg = new IMAGE();
IMAGE* bGuardImg = new IMAGE();
IMAGE* bKingImg = new IMAGE();
IMAGE* bElephant = new IMAGE();



void initImage();
//判断一个ExMessage对应的鼠标事件的鼠标位置是否在框里(不含边界)
bool mouseMessageInBox(ExMessage* message, short x, short y, short x1, short y1);
//根据鼠标点击的相对于窗口左上角的坐标获取点的棋子的坐标,结果用后两个指针返回,
//如果点击的不是棋子那就返回两个-1
void getPieceXYByXY(int x, int y, int* pX, int* pY);

void redrawChess(Chess* chess);//定义一个画棋盘的函数
void drawPiece(int index, short piece);//定义一个画棋子的函数

int main()
{
	initImage();

	Chess* chess = new Chess(true);//红先黑后的新棋盘
	
	//加载play.png
	IMAGE* playPng = new IMAGE();
	loadimage(playPng, L"resources\\play.png");

	//创建用于接收消息的结构体
	ExMessage message;

	// 初始化图形窗口
	initgraph(800, 800);

	while (true)//主游戏循环
	{
		if (chess->getState() == 0)//游戏未开始，绘制play.png并监听鼠标事件。
		{
			//clearrectangle(0, 0, WIDTH, HEIGHT);
			putimage(0, 0, playPng);

			//获取一个消息
			message = getmessage();

			//如果不是鼠标左键按下消息就不管，直接下一次循环
			if (message.message != WM_LBUTTONDOWN)continue;

			//是的话判断鼠标按下位置是否在play按钮对应区域(289,357,509,441)
			if (mouseMessageInBox(&message, 289, 357, 509, 441))
			{
				chess->setState(1);
				redrawChess(chess);

			}


		}
		if (chess->getState() == 1)
		{
			Stack_list<int, 250> tempValidMoves = chess->getValidMoves(false);

			/*Sleep(2000);
			Piece* (*pieceArry)[10][9] = chess->getPieceArry();
			//(*pieceArry)[6][4]->move(4, 5);
			//redrawChess(chess);

			cout << *pieceArry[6][4] << endl;
			cout << (*pieceArry)[6][4] << endl;*/
			//获取一个消息
			message = getmessage();

			//如果不是鼠标左键按下消息就不管，直接下一次循环
			if (message.message != WM_LBUTTONDOWN)continue;
			static int selectedPx = -1, selectedPy = -1;                   //存放选中的棋子的两个变量，-1，-1意味着未选择棋子
			int px = 0, py = 0;
			getPieceXYByXY(message.x, message.y, &px, &py);
			//用户点的地方是非法区域
			//if (px == -1) continue;
			if (px == -1)
			{
				chess->rollBack();
				redrawChess(chess);
				continue;
			}

			//用户尚未选择棋子
			if (selectedPx == -1)
			{
				//cout << (*(chess->getPieceArry())[py][px]) << endl;
				//cout << (*(chess->getPieceArry())[6][4]) << endl;
				//点的位置也没有棋子
				if (!chess->xyHavePiece(px,py)) continue;
				else//else代表点的位置有棋子
				{
					//判断此棋子是否是我方棋子
					if (((bool)(chess->getPiece(px, py) / 10)) ^ chess->getNowPlayer())
					{
						//是的话就选中
						cout << "选中了" << px << " " << py << endl;
						selectedPx = px;
						selectedPy = py;
					}
					else continue;//不是的话就忽略

				}
			}
			else //用户已经选择了棋子
			{
				if (px == selectedPx && py == selectedPy)
				{
					selectedPx = -1;
					selectedPy = -1;
				}
				//如果可以移动到指定位置那就移动，之后清空选择的棋子
				if (chess->canMove(selectedPx, selectedPy, px, py))//先进行可移动判定
				{
					//移动棋
					chess->move(selectedPx, selectedPy, px, py);

					if (chess->isInCheck(!chess->getNowPlayer()))
					{
						cout << "将军" << endl;
						chess->rollBack();
						MessageBox(NULL, L"帅被将军", L"提示", MB_OK);
						continue;
					}
					//重新绘制棋盘
					redrawChess(chess);
					//移动之后判断是否被将死
					//if (chess->isDie())
					//{

					//	cout << ((!chess->getNowPlayer()) ? "红" : "黑") << "方胜" << endl;
					//	((!chess->getNowPlayer()) ? MessageBox(NULL, L"红方胜", L"提示", MB_OK) : MessageBox(NULL, L"黑方胜", L"提示", MB_OK));

					//}

					int tempMove;
					minMaxSearch(chess,true, 20000, false, 0, tempMove);
					cout << tempMove << endl;
					chess->move(tempMove);
					redrawChess(chess);

				}
				//清空选择的棋子
				selectedPx = -1;
				selectedPy = -1;
			}
		}
	}





	Sleep(10000);
	return 0;
}

void redrawChess(Chess* chess)
{

	putimage(0, 0, boardImg);

	chess->forBoard(drawPiece);

}
void drawPiece(int index,short piece)
{
	if (!isInBoard(index)) return;
	//计算出棋子图片位置之后画在屏幕上，但是TODO：bug透明背景是黑色的
	int drawX = (83 - PIECE_WIDTH / 2) + 79 * getX(index);
	int drawY = (44 - PIECE_HEIGHT / 2) + 79 * getY(index);
	switch (piece)
	{
	case NO_PIECE:		   break;
	case R_KING:		   putimage(drawX, drawY, rKingImg);break;
	case R_CANNON:		   putimage(drawX, drawY, rCannonImg);break;
	case R_CAR:			   putimage(drawX, drawY, rCarImg);break;
	case R_ELEPHANT:	   putimage(drawX, drawY, rElephant);break;
	case R_GUARD:		   putimage(drawX, drawY, rGuardImg);break;
	case R_HORSE:		   putimage(drawX, drawY, rHorseImg);break;
	case R_SOLDIER:		   putimage(drawX, drawY, rSoldierImg);break;
	case B_KING:		   putimage(drawX, drawY, bKingImg); break;
	case B_CANNON:		   putimage(drawX, drawY, bCannonImg); break;
	case B_CAR:			   putimage(drawX, drawY, bCarImg); break;
	case B_ELEPHANT:	   putimage(drawX, drawY, bElephant); break;
	case B_GUARD:		   putimage(drawX, drawY, bGuardImg); break;
	case B_HORSE:		   putimage(drawX, drawY, bHorseImg); break;
	case B_SOLDIER:		   putimage(drawX, drawY, bSoldierImg);break;

	}
}
void initImage()
{
	loadimage(playImg, L"resources\\play.png");
	loadimage(boardImg, L"resources\\棋盘.png");
	loadimage(rSoldierImg, L"resources\\红兵.png");
	loadimage(rCarImg, L"resources\\红車.png");
	loadimage(rHorseImg, L"resources\\红马.png");
	loadimage(rCannonImg, L"resources\\红炮.png");
	loadimage(rGuardImg, L"resources\\红仕.png");
	loadimage(rKingImg, L"resources\\红帅.png");
	loadimage(rElephant, L"resources\\红相.png");
	loadimage(bSoldierImg, L"resources\\黑卒.png");
	loadimage(bCarImg, L"resources\\黑車.png");
	loadimage(bHorseImg, L"resources\\黑马.png");
	loadimage(bCannonImg, L"resources\\黑炮.png");
	loadimage(bGuardImg, L"resources\\黑士.png");
	loadimage(bKingImg, L"resources\\黑将.png");
	loadimage(bElephant, L"resources\\黑象.png");

}


bool mouseMessageInBox(ExMessage* message, short x, short y, short x1, short y1)
{
	/* *越往上越小
	 *WM_MOUSEFIRST
	 *鼠标消息1
	 *.........
	 *鼠标消息n
	 *WM_MOUSELAST
	 *越往下越大
	 */
	if (message->message < WM_MOUSEFIRST || message->message > WM_MOUSELAST) return false;//如果不是鼠标消息的话就返回false
	if (message->x > x && message->y > y && message->x < x1 && message->y < y1) return true;//如果在区域里面就返回true，不在就返回false
	return false;
}

void getPieceXYByXY(int x, int y, int* pX, int* pY)
{
	x -= (83 - PIECE_WIDTH / 2);
	y -= (44 - PIECE_HEIGHT / 2);

	*pX = x / 79;
	*pY = y / 79;
	if (x < 0 || y < 0)
	{
		*pX = -1;
		*pY = -1;
	}
	if (x % 79 > PIECE_WIDTH || y % 79 > PIECE_HEIGHT)
	{
		*pX = -1;
		*pY = -1;
	}
	if (x > 9 * 79 || y > 10 * 79)
	{
		*pX = -1;
		*pY = -1;
	}


}